function(util_exe_func exename srcname)
  add_executable(${exename} ${srcname})
  target_link_libraries(${exename} core)
  bob_export_target(${exename})
  bob_end_subdir()
endfunction(util_exe_func)

function(test_exe_func exename srcname)
  if(IS_TESTING)
    add_executable(${exename} ${srcname})
  else()
    add_executable(${exename} EXCLUDE_FROM_ALL ${srcname})
  endif()
  target_link_libraries(${exename} core)
endfunction(test_exe_func)

# Mesh validity/statistics utilities
util_exe_func(verify verify.cc)
util_exe_func(describe describe.cc)
test_exe_func(outputcontrol outputcontrol.cc)
test_exe_func(quality quality.cc)
test_exe_func(writeVtxPtn writeVtxPtn.cc)
test_exe_func(verify_2nd_order_shapes verify_2nd_order_shapes.cc)
test_exe_func(verify_convert verify_convert.cc)

# Geometric model utilities
if(ENABLE_SIMMETRIX)
  util_exe_func(mdlConvert mdlConvert.cc)
endif()
util_exe_func(mkmodel mkmodel.cc)
util_exe_func(mktopomodel mktopomodel.cc)
util_exe_func(modelInfo modelInfo.cc)

# Mesh generation utilities
util_exe_func(box box.cc)
util_exe_func(uniform uniform.cc)
util_exe_func(classifyThenAdapt classifyThenAdapt.cc)
util_exe_func(refine2x refine2x.cc)
util_exe_func(serialize serialize.cc)
util_exe_func(tetrahedronize tetrahedronize.cc)
util_exe_func(intrude intrude.cc)
util_exe_func(extrude extrude.cc)

# Mesh conversion/formatting utilities
util_exe_func(from_gmsh gmsh.cc)
util_exe_func(from_ansys ansys.cc)
util_exe_func(from_neper neper.cc)
util_exe_func(from_ugrid ugrid.cc)
util_exe_func(nektar_align nektar_align.cc)
util_exe_func(icesheet icesheet.cc)
if(ENABLE_OMEGA_H)
  util_exe_func(smb2osh smb2osh.cc)
  util_exe_func(osh2smb osh2smb.cc)
endif()

# Mesh rendering/visualization utilities
util_exe_func(render render.cc)
util_exe_func(renderClass renderClass.cc)
util_exe_func(render_ascii render_ascii.cc)
if(ENABLE_VIZ)
  test_exe_func(viz_test viz.cc)
endif()

# Aniso statistic ans size-field visualization utilities
util_exe_func(measureAnisoStats measureAnisoStats.cc)
util_exe_func(measureIsoStats measureIsoStats.cc)
util_exe_func(visualizeAnisoSizes visualizeAnisoSizes.cc)
if(ENABLE_SIMMETRIX)
  util_exe_func(runSimxAnisoAdapt runSimxAnisoAdapt.cc)
endif()

if(ENABLE_SIMMETRIX)
  util_exe_func(convert convert.cc)
  util_exe_func(ph_convert ../phasta/ph_convert.cc)
  if(SIMMODSUITE_SimAdvMeshing_FOUND)
    util_exe_func(generate generate.cc)
    if(SIM_DOT_VERSION VERSION_GREATER 12.0.171000)
      util_exe_func(rm_extrusion rm_extrusion.cc)
    endif()
  endif()
  util_exe_func(snap snap.cc)
endif()

# Mesh partitioning utilities
util_exe_func(split split.cc)
util_exe_func(zsplit zsplit.cc)
util_exe_func(collapse collapse.cc)
util_exe_func(repartition repartition.cc)
util_exe_func(balance balance.cc)
test_exe_func(elmBalance elmBalance.cc)
test_exe_func(vtxBalance vtxBalance.cc)
test_exe_func(vtxElmBalance vtxElmBalance.cc)
test_exe_func(vtxElmMixedBalance vtxElmMixedBalance.cc)
test_exe_func(vtxEdgeElmBalance vtxEdgeElmBalance.cc)
test_exe_func(ghost ghost.cc)
test_exe_func(ghostMPAS ghostMPAS.cc)
test_exe_func(ghostEdge ghostEdge.cc)
test_exe_func(loadPart loadPart.cc)
test_exe_func(ugridptnstats ugridptnstats.cc)
test_exe_func(gap gap.cc)
test_exe_func(applyMatrixFunc applyMatrixFunc.cc)
if(ENABLE_ZOLTAN)
  util_exe_func(zbalance zbalance.cc)
  util_exe_func(ptnParma ptnParma.cc)
endif()

# Mesh improvement utilities
util_exe_func(reorder reorder.cc)
util_exe_func(fixshape fixshape.cc)
util_exe_func(fixlayer fixlayer.cc)
util_exe_func(fixDisconnected fixDisconnected.cc)
util_exe_func(scale scale.cc) 

# Phasta utilities
util_exe_func(chef ../phasta/chef.cc)
util_exe_func(condense ../phasta/condense.cc)
util_exe_func(threshold ../phasta/threshold.cc)
util_exe_func(chefReadUrPrep ../phasta/readUrPrep.cc)
if(NOT APPLE)
  util_exe_func(chefStream ../phasta/chefStream.cc)
  util_exe_func(adaptLvlSetLoop ../phasta/adaptLvlSet_loop.cc)
endif()
if(ENABLE_SIMMETRIX)
  util_exe_func(cut_interface ../phasta/cut_interface.cc)
  util_exe_func(migrate_interface ../phasta/migrate_interface.cc)
endif()
if(SIMMODSUITE_SimAdvMeshing_FOUND)
  target_compile_definitions(chef PRIVATE -DHAVE_SIMADVMESHING)
  target_compile_definitions(cut_interface PRIVATE -DHAVE_SIMADVMESHING)
endif()

# Unit tests / functionality regression tests
test_exe_func(qr qr.cc)
test_exe_func(eigen_test eigen_test.cc)
test_exe_func(integrate integrate.cc)
test_exe_func(align align.cc)
test_exe_func(field_io field_io.cc)
test_exe_func(tensor tensor.cc)
test_exe_func(test_AD test_AD.cc)
test_exe_func(spr_test spr_test.cc)
test_exe_func(reposition reposition.cc)
test_exe_func(writeIPFieldTest writeIPFieldTest.cc)
test_exe_func(shapefun shapefun.cc)
test_exe_func(shapefun2 shapefun2.cc)
test_exe_func(bezierElevation bezierElevation.cc)
test_exe_func(bezierMesh bezierMesh.cc)
test_exe_func(bezierMisc bezierMisc.cc)
test_exe_func(bezierRefine bezierRefine.cc)
test_exe_func(bezierSubdivision bezierSubdivision.cc)
test_exe_func(bezierValidity bezierValidity.cc)
test_exe_func(ma_test_analytic_model ma_test_analytic_model.cc)
test_exe_func(fusion fusion.cc)
test_exe_func(fusion2 fusion2.cc)
test_exe_func(fusion3 fusion3.cc)
test_exe_func(1d 1d.cc)
test_exe_func(base64 base64.cc)
test_exe_func(test_pumi pumi.cc)
test_exe_func(xgc_split xgc_split.cc)
test_exe_func(ma_insphere ma_insphere.cc)
test_exe_func(ma_test ma_test.cc)
test_exe_func(aniso_ma_test aniso_ma_test.cc)
test_exe_func(torus_ma_test torus_ma_test.cc)
test_exe_func(dg_ma_test dg_ma_test.cc)
test_exe_func(prismCodeMatch ../ma/prismCodeMatch.cc)
test_exe_func(pyramidCodeMatch ../ma/pyramidCodeMatch.cc)
test_exe_func(newdim newdim.cc)
test_exe_func(construct construct.cc)
test_exe_func(constructThenGhost constructThenGhost.cc)
test_exe_func(construct_bottom_up construct_bottom_up.cc)
test_exe_func(embedded_edges embedded_edges.cc)
test_exe_func(test_scaling test_scaling.cc)
test_exe_func(mixedNumbering mixedNumbering.cc)
test_exe_func(test_verify test_verify.cc)
test_exe_func(hierarchic hierarchic.cc)
test_exe_func(poisson poisson.cc)
test_exe_func(ph_adapt ph_adapt.cc)
test_exe_func(assert_timing assert_timing.cc)
test_exe_func(create_mis create_mis.cc)
test_exe_func(fieldReduce fieldReduce.cc)
test_exe_func(test_integrator test_integrator.cc)
test_exe_func(test_matrix_gradient test_matrix_grad.cc)
if(ENABLE_DSP)
  test_exe_func(graphdist graphdist.cc)
  test_exe_func(moving moving.cc)
endif()
if(ENABLE_SIMMETRIX)
  test_exe_func(curvetest curvetest.cc)
  test_exe_func(curve_to_bezier curve_to_bezier.cc)
  test_exe_func(inClosureOf_test inClosureOf_test.cc)
  test_exe_func(degenerate_test degenerateSurfs.cc)
  test_exe_func(simZBalance simZBalance.cc)
  test_exe_func(crack_test crack_test.cc)
endif()

# send all the newly added utility executable targets
# back up to the parent (root) scope to be included
# in scorec-config.cmake
set(TARGETS ${TARGETS} PARENT_SCOPE)

# Add the nightly testing script, if needed
if(IS_TESTING)
  include(testing.cmake)
endif()

if(ENABLE_SIMMETRIX)
  #executables which call only Simmetrix functions
  include_directories(${PROJECT_BINARY_DIR}/gmi_sim)
  util_exe_func(simTranslate simTranslate.cc)
  if(SIM_PARASOLID)
    util_exe_func(sim_part sim_part.cc)
    if(SIMMODSUITE_SimAdvMeshing_FOUND)
      util_exe_func(sim_countBL sim_countBL.cc)
      target_compile_definitions(sim_part PRIVATE -DHAVE_SIMADVMESHING)
      target_compile_definitions(sim_countBL PRIVATE -DHAVE_SIMADVMESHING)
    endif()
    util_exe_func(simSpjToSmd simSpjToSmd.cc)
    if(SIMMODSUITE_SimDiscrete_FOUND)
      util_exe_func(simDiscrete simDiscrete.cc)
    endif()
  endif()
endif()

bob_end_subdir()
